package com.hiwan.system.security.filter;


import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.hiwan.platform.util.IPUtils;
import com.hiwan.platform.utils.DateUtils;
import com.hiwan.platform.utils.StringUtils;
import com.hiwan.system.common.web.Servlets;
import com.hiwan.system.pojo.LoginInfo;
import com.hiwan.system.security.UsernamePasswordToken;
import com.hiwan.system.service.login.LoginService;
import com.hiwan.system.util.IdGen;
import com.hiwan.system.util.UserCacheUtils;


/**
 * 
 * Datetime   ： 2016年1月5日 下午11:35:02<br>
 * Title      :  FormAuthenticationFilter.java<br>
 * Description:   表单验证（包含验证码）过滤类<br>
 * Company    :  hiwan<br>
 * @author cbj
 *
 */
@Component
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {

	public static final String DEFAULT_CAPTCHA_PARAM = "validateCode";
	public static final String DEFAULT_MOBILE_PARAM = "mobileLogin";
	public static final String DEFAULT_MESSAGE_PARAM = "message";
	
	private Logger logger = LoggerFactory.getLogger(getClass());

	private String captchaParam = DEFAULT_CAPTCHA_PARAM;
	private String mobileLoginParam = DEFAULT_MOBILE_PARAM;
	private String messageParam = DEFAULT_MESSAGE_PARAM;
	@Autowired
	private LoginService loginService;

	protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
		String username = getUsername(request);
		String password = getPassword(request);
		if (password==null){
			password = "";
		}
		boolean rememberMe = isRememberMe(request);
		String host = StringUtils.getRemoteAddr((HttpServletRequest)request);
		String captcha = getCaptcha(request);
		boolean mobile = isMobileLogin(request);
		return new UsernamePasswordToken(username, password.toCharArray(), rememberMe, host, captcha, mobile);
	}

	public String getCaptchaParam() {
		return captchaParam;
	}

	protected String getCaptcha(ServletRequest request) {
		return WebUtils.getCleanParam(request, getCaptchaParam());
	}

	public String getMobileLoginParam() {
		return mobileLoginParam;
	}
	
	protected boolean isMobileLogin(ServletRequest request) {
        return WebUtils.isTrue(request, getMobileLoginParam());
    }
	
	public String getMessageParam() {
		return messageParam;
	}
	
	/**
	 * 登录成功之后跳转URL
	 */
	public String getSuccessUrl() {
		return super.getSuccessUrl();
	}
	
	
	
	/**
	 * 登录成功后执行的方法
	 */
	@Override
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
			ServletResponse response) throws Exception {
		LoginInfo loginInfo = new LoginInfo();
		loginInfo.setLoginId(IdGen.uuid());
		loginInfo.setUserId(UserCacheUtils.getId());
		loginInfo.setUserOrgId(UserCacheUtils.getOrgId());
		loginInfo.setLoginTime(DateUtils.getDateTime());
		loginInfo.setIp(IPUtils.getRemoteIpAddr(Servlets.getRequest()));
		try {
			loginService.add(loginInfo);
			//将登录日志id放入session，在用户登出的时候，使用此id更新登出时间
			UserCacheUtils.putCache("loginId", loginInfo.getLoginId());
		} catch (Exception e) {
			logger.warn("登录日志记录错误{}，错误信息{}",loginInfo,e);
		}
		return super.onLoginSuccess(token, subject, request, response);
	}

	@Override
	protected void issueSuccessRedirect(ServletRequest request,
			ServletResponse response) throws Exception {
//		Principal p = UserUtils.getPrincipal();
//		if (p != null && !p.isMobileLogin()){
			 WebUtils.issueRedirect(request, response, getSuccessUrl(), null, true);
//		}else{
//			super.issueSuccessRedirect(request, response);
//		}
	}

	/**
	 * 登录失败调用事件
	 */
	@Override
	protected boolean onLoginFailure(AuthenticationToken authcToken,
			AuthenticationException e, ServletRequest request, ServletResponse response) {
		String className = e.getClass().getName(), message = "";
		if (IncorrectCredentialsException.class.getName().equals(className)
				|| UnknownAccountException.class.getName().equals(className)){
			message = "用户ID或密码错误, 请重试.";
		}
		else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")){
			message = StringUtils.replace(e.getMessage(), "msg:", "");
		}
		else{
			message = "系统出现点问题，请稍后再试！";
			e.printStackTrace(); // 输出到控制台
		}
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        request.setAttribute(getFailureKeyAttribute(), className);
        request.setAttribute(getMessageParam(), message);
        request.setAttribute("username",token.getUsername());
        request.setAttribute("password",token.getPassword());
        request.setAttribute("mobileLogin",token.isMobileLogin() + "");
        return true;
	}
	
}